import { useEffect, useState } from "react";
import { useLatest } from "react-use";

import { FormSelect, FormTextInput } from "metabase/forms";
import { Loader } from "metabase/ui";
import { useExtractColumnsFromQueryMutation } from "metabase-enterprise/api";
import * as Lib from "metabase-lib";

type NativeQueryColumnSelectProps = {
  name: string;
  label: string;
  description: string;
  placeholder: string;
  query: Lib.Query;
};

export function NativeQueryColumnSelect({
  name,
  label,
  description,
  placeholder,
  query,
}: NativeQueryColumnSelectProps) {
  const [columns, setColumns] = useState<string[] | null>(null);
  const [extractColumns, { isLoading }] = useExtractColumnsFromQueryMutation();

  const queryRef = useLatest(query);

  useEffect(() => {
    let isCancelled = false;
    if (
      columns &&
      Lib.areLegacyQueriesEqual(
        Lib.toLegacyQuery(queryRef.current),
        Lib.toLegacyQuery(query),
      )
    ) {
      return;
    }

    const extract = async () => {
      try {
        const result = await extractColumns({
          query: Lib.toJsQuery(query),
        }).unwrap();

        if (!isCancelled) {
          // Only use columns if we got at least one
          setColumns(result.columns.length > 0 ? result.columns : null);
        }
      } catch (error) {
        // On error, fall back to text input
        if (!isCancelled) {
          setColumns(null);
        }
      }
    };

    extract();

    return () => {
      isCancelled = true;
    };
  }, [extractColumns, query, queryRef, columns]);

  // If we successfully extracted columns, show a selector
  if (columns && columns.length > 0) {
    return (
      <FormSelect
        name={name}
        rightSection={isLoading ? <Loader size="sm" /> : null}
        disabled={isLoading}
        label={label}
        description={description}
        placeholder={placeholder}
        data={columns.map((col) => ({ value: col, label: col }))}
      />
    );
  }

  // Otherwise, fall back to text input
  return (
    <FormTextInput
      name={name}
      label={label}
      placeholder={placeholder}
      description={description}
    />
  );
}
